Skip to content

fix: stop choppy screen resize when switching modes#1187

Closed
BigSimmo wants to merge 15 commits into
mainfrom
cursor/fix-mode-switch-lag-22f6
Closed

fix: stop choppy screen resize when switching modes#1187
BigSimmo wants to merge 15 commits into
mainfrom
cursor/fix-mode-switch-lag-22f6

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fix cross-mode search performance findings: prescribing catalogue debounce/abort/fields=index, differentials abort/debounce, universal documents typeahead soft-timeout (750ms), shared (search-app) shell to avoid composer remount, and Answer rate-limit in-memory fallback outside production.
  • Fix Bugbot regressions: shared-shell pathname navigation (/services/dsm) syncs searchMode during render (no stale-mode paint) even when the query string is unchanged; extracted ClinicalDashboard lazy imports to stay under the maintainability budget.

RAG impact: no retrieval behaviour change — typeahead documents domain timeout and shell URL sync only; ranking formulas and full /api/search retrieval path unchanged.

Verification

  • npm run verify:pr-local — focused Vitest on touched sources (362) plus api-rate-limit / search-shell / universal / route / site-map suites green; docs:check-index OK
  • UI verification not run: full verify:ui not required for this pass; mode-home smoke via npm run ensure returned HTTP 200 for /, /services, /dsm, /documents/search, /therapy-compass, /?mode=prescribing, and /api/answer/stream returned 200 after the rate-limit fallback fix
  • Verification not run: eval:retrieval:latency / soak / live OpenAI canary — approval-gated provider work; not needed for timeout-only typeahead change

Risk and rollout

  • Risk: medium — shared layout remount change and rate-limit fallback behaviour in non-production; production Answer/upload still fail closed when the durable limiter is unavailable
  • Rollback: revert this PR; mode routes return to per-segment GlobalSearchShell layouts and prior timeout/fallback behaviour
  • Provider or production effects: None

Clinical Governance Preflight

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval
  • Supabase target remains [REDACTED] ([REDACTED])
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed

Notes

  • Prescribing list rows keep the full catalogue payload so Safety/Monitoring filters and patient alerts still see section-derived signals; keystroke storms are controlled by debounce + abort. fields=index remains for identity-only consumers (cross-mode links).
  • Live hybrid RPC cold tails remain a separate approval-gated follow-up.

Summary by CodeRabbit

  • New Features

    • Added consistent loading screens across search modes and routes.
    • Added improved routing between dashboard and standalone search modes.
    • Forms home now provides the appropriate Readiness checks shortcut.
  • Bug Fixes

    • Prevented unnecessary document viewer reloads when changing pages or chunks.
    • Improved phone navigation by resetting scroll and search chrome state.
    • Reduced visual flicker during composer, sidebar, and page transitions.
    • Improved loading alignment and fallback behavior on mobile devices.
  • Documentation

    • Updated route and search-chrome behavior guidance.

cursoragent and others added 5 commits July 24, 2026 19:47
Mode switches animated phone composer reserve because searchMode updated
before the pathname landed, briefly leaving isStandaloneModeHome false and
running the 200ms padding transition. Detect mode homes from pathname only,
navigate without optimistic mode state, and limit padding transitions to
scroll-hide.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
After the reserve-flip fix, related choppiness remained from eager
crossModeSearch chrome updates, inherited phone scroll/hide across mode
homes, a hero-portal null gap while slots rebound, a taller mode-home
loading skeleton, and services/forms contentAlign jumping after registry
load. Navigate out of the dashboard without rewriting chrome, reset
scroll-hide on pathname change, keep the default composer until the
portal attaches, align the skeleton to the shell header token, and keep
loading homes top-aligned on phone.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@supabase

supabase Bot commented Jul 25, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR centralizes standalone mode-home detection, changes navigation to follow URL ownership, standardizes route loading skeletons, adjusts mobile layout transitions, prevents unnecessary remounts, stabilizes composer handoffs, dynamically loads ClinicalDashboard, and adds source-level contract tests and review records.

Changes

Mode routing and shell stabilization

Layer / File(s) Summary
Route ownership and URL-driven shell navigation
src/lib/search-route-ownership.ts, src/app/(search-app)/page.tsx, src/components/clinical-dashboard/..., src/lib/private-search-scope.ts
Standalone paths and dashboard-owned hrefs now control mode synchronization, navigation branching, scroll resets, dynamic dashboard loading, and direct mode-home redirects.
Mode-home loading and layout contracts
src/app/(search-app)/*/loading.tsx, src/components/mode-home-page-skeleton.tsx, src/components/forms/..., src/components/services/..., src/app/globals.css, tests/*
Mode routes use ModeHomeRouteLoading; phone loading alignment and reserve transitions are updated, forms receive a server-derived slug, and loading/client-boundary contracts are tested.
Composer mounting and remount prevention
src/components/clinical-dashboard/master-search-header.tsx, src/app/(search-app)/documents/[id]/page.tsx, src/components/forms/forms-search-results-page.tsx, tests/document-detail-performance.test.ts
The default composer remains visible until its portal host attaches, while document and forms views avoid unnecessary remounts.
Ledger and search-chrome invariants
docs/branch-review-ledger.md, docs/search-chrome-behaviour.md
Review records and invariants document the updated routing, loading, transition, hydration, portal, and residual architecture behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested labels: codex

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main mode-switch resize fix.
Description check ✅ Passed The description matches the template sections and includes summary, verification, risk, governance, and notes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/fix-mode-switch-lag-22f6
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch cursor/fix-mode-switch-lag-22f6

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

cursoragent and others added 4 commits July 25, 2026 01:45
Reset bottom-composer hidden state during render on pathname change
instead of setState-in-effect, and drop the unused hero-portal fallback
flag now that the default composer stays mounted until the host attaches.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

CI triage

CI failed on this PR. Automated classification of the 3 failed job(s):

  • Static PR checksneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • Production UIneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • PR requiredneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.

Compared with main CI run #5251 (success).

Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger.

cursoragent and others added 5 commits July 25, 2026 13:56
Append review of mode/page loading and navigation architecture at HEAD
0ef62ff: P1 shell bundle + hydration blanking; residual remount/tools dual.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Parallel loading review found hard-load blanking from ClientHydrationBoundary,
mismatched/missing mode-home loading skeletons, forms catalog in the client
chunk, ClinicalDashboard static weight on namespaced routes, sidebar column
animation on remount, forms query remounts, and document viewer remounts on
page flips. Paint RSC children immediately, align ModeHomeRouteLoading, wire
mode-home loading.tsx files, server-pass the default form slug, dynamic-import
ClinicalDashboard, gate sidebar transitions after mount, and stop unnecessary
remount keys.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Keeps ClinicalDashboard inside the maintainability budget after the
loading-performance pass, and shares the remount-safe sidebar transition
gate with GlobalSearchShell.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@cursor

cursor Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Parallel loading review follow-up (this tip)

Ran explore×3 + live debug across modes/pages. Confirmed: Answer↔namespaced remount dominates settle (~0.6–1.2s); hero portal rebinds; registry pop-in after paint.

Landed quick wins: remove ClientHydrationBoundary blanking; ModeHomeRouteLoading phone top-align; mode-home loading.tsx alignment/additions; forms server defaultFormSlug + client-boundary test; dynamic ClinicalDashboard; sidebar column transition mount-gate; forms drop key={query}; DocumentViewer key={id}; therapy Suspense skeleton; redirect /?mode=services|forms.

Residual: unify dashboard/standalone chrome; stable shell-owned hero slot; registry abort+LRU/summary; Tools dual entry #007; prescribing full-catalogue cliff.

verify:cheap / typecheck / focused loading contracts green on this tip.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@BigSimmo
BigSimmo marked this pull request as ready for review July 25, 2026 16:36
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
tests/document-detail-performance.test.ts (1)

21-24: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift

Add behavioral coverage for same-document transitions.

These assertions verify source text only. Add a runtime test that changes page/chunk for the same document and confirms the viewer updates without remounting or reloading, while a different document still remounts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/document-detail-performance.test.ts` around lines 21 - 24, Add runtime
coverage in the document detail performance test around the DocumentViewer flow:
navigate between pages or chunks for the same document and assert the existing
viewer instance remains mounted without reloading, then switch to a different
document and assert the viewer remounts. Keep the existing source-text
assertions and use the test’s established navigation and viewer-loading helpers.
src/components/forms/forms-home-page.tsx (1)

43-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Centralize the form-detail href.

Use the existing route ownership/catalog mechanism for this internal destination rather than adding "/forms/..." inline here.

As per coding guidelines, “build hrefs from the existing application source catalogs rather than scattered hardcoded strings.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/forms/forms-home-page.tsx` at line 43, Update the href in the
forms home page component to use the existing route ownership/catalog mechanism
for the form-detail destination, passing defaultFormSlug through that
centralized route builder instead of constructing the "/forms/..." path inline.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`(search-app)/page.tsx:
- Around line 81-87: Update the redirect built by appModeHomeHref in the
initialSearchMode services/forms branch to preserve the supported query alias by
reading and forwarding the query parameter alongside q. Ensure requests using
query, such as query=mania with run=1, retain the search text and
submitted-search state when redirected.

In `@src/components/clinical-dashboard/master-search-header.tsx`:
- Around line 1890-1895: Update renderSearchComposer and its desktop fallback
condition so the hero-specific sm:hidden class is applied only when the desktop
home composer portal is actually attached, not merely when isHeroDesktopComposer
is true. Ensure the default composer remains visible while
desktopHomeComposerActive is true and desktopHomeComposerHost is null, then
validate with npm run ensure and npm run verify:ui.

In `@src/lib/private-search-scope.ts`:
- Around line 75-80: Update removePrivateScopeRefFromUrl to include hash in its
Location shape and preserve the current fragment when constructing the
replacement URL. Append location.hash after the pathname and updated query
string so removing scopeRef does not change the active in-page section.

---

Nitpick comments:
In `@src/components/forms/forms-home-page.tsx`:
- Line 43: Update the href in the forms home page component to use the existing
route ownership/catalog mechanism for the form-detail destination, passing
defaultFormSlug through that centralized route builder instead of constructing
the "/forms/..." path inline.

In `@tests/document-detail-performance.test.ts`:
- Around line 21-24: Add runtime coverage in the document detail performance
test around the DocumentViewer flow: navigate between pages or chunks for the
same document and assert the existing viewer instance remains mounted without
reloading, then switch to a different document and assert the viewer remounts.
Keep the existing source-text assertions and use the test’s established
navigation and viewer-loading helpers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f6ed9aa-184b-4eeb-89ab-eb5be5743760

📥 Commits

Reviewing files that changed from the base of the PR and between 8284fcd and 7bceebf.

📒 Files selected for processing (34)
  • docs/branch-review-ledger.md
  • docs/search-chrome-behaviour.md
  • scripts/check-maintainability-budgets.mjs
  • src/app/(search-app)/differentials/loading.tsx
  • src/app/(search-app)/documents/[id]/page.tsx
  • src/app/(search-app)/dsm/loading.tsx
  • src/app/(search-app)/factsheets/loading.tsx
  • src/app/(search-app)/favourites/loading.tsx
  • src/app/(search-app)/forms/loading.tsx
  • src/app/(search-app)/forms/page.tsx
  • src/app/(search-app)/formulation/loading.tsx
  • src/app/(search-app)/page.tsx
  • src/app/(search-app)/specifiers/loading.tsx
  • src/app/(search-app)/therapy-compass/loading.tsx
  • src/app/globals.css
  • src/components/ClinicalDashboard.tsx
  • src/components/clinical-dashboard/global-search-shell.tsx
  • src/components/clinical-dashboard/master-search-header.tsx
  • src/components/clinical-dashboard/shared-search-app-shell.tsx
  • src/components/clinical-dashboard/use-hide-on-scroll.ts
  • src/components/clinical-dashboard/use-sidebar-column-transition.ts
  • src/components/forms/forms-home-page.tsx
  • src/components/forms/forms-search-results-page.tsx
  • src/components/mode-home-page-skeleton.tsx
  • src/components/services/services-home-page.tsx
  • src/lib/private-search-scope.ts
  • src/lib/search-route-ownership.ts
  • tests/document-detail-performance.test.ts
  • tests/forms-client-boundary.test.ts
  • tests/mode-home-loading-contract.test.ts
  • tests/mode-home-main-align.test.ts
  • tests/search-route-ownership.test.ts
  • tests/therapy-compass-mode-wiring.test.ts
  • tests/ui-phone-scroll.spec.ts

Comment on lines +81 to +87
if (initialSearchMode === "services" || initialSearchMode === "forms") {
redirect(
appModeHomeHref(initialSearchMode, {
query: firstSearchParam(params.q)?.trim(),
focus: firstSearchParam(params.focus) === "1",
run: firstSearchParam(params.run) === "1",
}),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the supported query alias.

GlobalStandaloneSearchShellClient reads q ?? query, but this redirect forwards only q. /?mode=services&query=mania&run=1 therefore lands without a query or submitted search.

Proposed fix
-        query: firstSearchParam(params.q)?.trim(),
+        query: firstSearchParam(params.q ?? params.query)?.trim(),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (initialSearchMode === "services" || initialSearchMode === "forms") {
redirect(
appModeHomeHref(initialSearchMode, {
query: firstSearchParam(params.q)?.trim(),
focus: firstSearchParam(params.focus) === "1",
run: firstSearchParam(params.run) === "1",
}),
if (initialSearchMode === "services" || initialSearchMode === "forms") {
redirect(
appModeHomeHref(initialSearchMode, {
query: firstSearchParam(params.q ?? params.query)?.trim(),
focus: firstSearchParam(params.focus) === "1",
run: firstSearchParam(params.run) === "1",
}),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(search-app)/page.tsx around lines 81 - 87, Update the redirect
built by appModeHomeHref in the initialSearchMode services/forms branch to
preserve the supported query alias by reading and forwarding the query parameter
alongside q. Ensure requests using query, such as query=mania with run=1, retain
the search text and submitted-search state when redirected.

Comment on lines +1890 to 1895
{/* Keep the default composer visible until the hero portal is actually
attached. Hiding on slotId alone left a null gap while the mode-home
slot remounted / MutationObserver rebound (mode-switch flicker). */}
{desktopHomeComposerActive && desktopHomeComposerHost ? null : renderSearchComposer("default")}
{desktopHomeComposerActive && desktopHomeComposerHost
? createPortal(renderSearchComposer("desktop-home"), desktopHomeComposerHost)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/components/clinical-dashboard/master-search-header.tsx"

echo "== file exists and size =="
wc -l "$file"

echo "== outline around relevant symbols =="
ast-grep outline "$file" --match renderSearchComposer --view expanded || true
ast-grep outline "$file" --match MasterSearchHeader --view expanded || true

echo "== relevant renderer slice =="
sed -n '1340,1425p' "$file"

echo "== relevant fallback/portals slice =="
sed -n '1860,1910p' "$file"

echo "== state references for desktopHomeComposerActive and desktopHomeComposerHost =="
rg -n "desktopHomeComposer(Active|Host)|desktopSearchPlacement|isHeroDesktopComposer|renderSearchComposer\\(\"default\"\\)" "$file"

Repository: BigSimmo/Database

Length of output: 8857


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/components/clinical-dashboard/master-search-header.tsx"

# Read-only behavioral probe: parse the render expression conditions without executing repo code.
python3 - <<'PY'
from pathlib import Path
import re

text = Path("src/components/clinical-dashboard/master-search-header.tsx").read_text()

def extract_block(start_marker, end_marker):
    start = text.index(start_marker)
    end = text.index(end_marker, start + len(start_marker))
    return text[start:end + len(end_marker)]

block = extract_block('const renderSearchComposer =', 'return null;')
print("== renderSearchComposer expression snippets ==")
for needle in ["className isHeroDesktopComposer", "isHeroDesktopComposer", "desktopHomeComposerHost ? createPortal", "desktopHomeComposerActive && desktopHomeComposerHost ? null", "desktopSearchPlacement!=", 'renderSearchComposer("default")']:
    for m in re.finditer(re.escape(needle), block):
        line = block[:m.start()].count("\n") + 1
        start = max(0, m.start() - 220)
        end = min(len(block), m.end() + 260)
        ctx = block[start:end].splitlines()
        print(f"\n[around line {line}] {needle}")
        for raw in ctx:
            print(raw)

model = [
    {"desktopSearchPlacement": "hero", "desktopHomeComposerActive": False, "desktopHomeComposerHost": False},
    {"desktopSearchPlacement": "hero", "desktopHomeComposerActive": True, "desktopHomeComposerHost": False},
    {"desktopSearchPlacement": "hero", "desktopHomeComposerActive": True, "desktopHomeComposerHost": True},
]
print("\n== simple class resolution model ==")
for state in model:
    is_hero = state["desktopSearchPlacement"] == "hero"
    classes = "sm:hidden" if state["desktopHomeComposerActive"] and state["desktopHomeComposerHost"] and is_hero else ("sm:sticky sm:top-[calc(4.75rem+env(safe-area-inset-top))]")
    show_default = state["desktopHomeComposerActive"] and state["desktopHomeComposerHost"]
    print(state, "show_default_fallback", show_default, "classes=", classes)
PY

Repository: BigSimmo/Database

Length of output: 304


Make the desktop fallback not invisible while the portal is attaching.

renderSearchComposer("default") keeps sm:hidden whenever isHeroDesktopComposer is true, so when desktopHomeComposerActive is true but desktopHomeComposerHost is still null, the default composer is mounted but hidden at desktop widths. Gate the hero class on portal attachment instead.

Proposed fix
-                          isHeroDesktopComposer
+                          isHeroDesktopComposer && desktopHomeComposerActive && desktopHomeComposerHost
                             ? "sm:hidden"
                             : "sm:sticky sm:top-[calc(4.75rem+env(safe-area-inset-top))]",

Validate the desktop mode-home handoff with npm run ensure and npm run verify:ui.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/clinical-dashboard/master-search-header.tsx` around lines 1890
- 1895, Update renderSearchComposer and its desktop fallback condition so the
hero-specific sm:hidden class is applied only when the desktop home composer
portal is actually attached, not merely when isHeroDesktopComposer is true.
Ensure the default composer remains visible while desktopHomeComposerActive is
true and desktopHomeComposerHost is null, then validate with npm run ensure and
npm run verify:ui.

Source: Coding guidelines

Comment on lines +75 to +80
/** Drop a restored private-scope ref from the current URL without a navigation. */
export function removePrivateScopeRefFromUrl(location: Pick<Location, "pathname" | "search"> = window.location) {
const params = new URLSearchParams(location.search);
params.delete("scopeRef");
const next = params.toString();
window.history.replaceState(null, "", `${location.pathname}${next ? `?${next}` : ""}`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the current hash fragment.

Clearing scopeRef also drops #sources (or another active section), breaking the current in-page location. Include hash in the location shape and append it to the replacement URL.

Proposed fix
-export function removePrivateScopeRefFromUrl(location: Pick<Location, "pathname" | "search"> = window.location) {
+export function removePrivateScopeRefFromUrl(
+  location: Pick<Location, "pathname" | "search" | "hash"> = window.location,
+) {
   const params = new URLSearchParams(location.search);
   params.delete("scopeRef");
   const next = params.toString();
-  window.history.replaceState(null, "", `${location.pathname}${next ? `?${next}` : ""}`);
+  window.history.replaceState(null, "", `${location.pathname}${next ? `?${next}` : ""}${location.hash}`);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/** Drop a restored private-scope ref from the current URL without a navigation. */
export function removePrivateScopeRefFromUrl(location: Pick<Location, "pathname" | "search"> = window.location) {
const params = new URLSearchParams(location.search);
params.delete("scopeRef");
const next = params.toString();
window.history.replaceState(null, "", `${location.pathname}${next ? `?${next}` : ""}`);
/** Drop a restored private-scope ref from the current URL without a navigation. */
export function removePrivateScopeRefFromUrl(
location: Pick<Location, "pathname" | "search" | "hash"> = window.location,
) {
const params = new URLSearchParams(location.search);
params.delete("scopeRef");
const next = params.toString();
window.history.replaceState(null, "", `${location.pathname}${next ? `?${next}` : ""}${location.hash}`);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/private-search-scope.ts` around lines 75 - 80, Update
removePrivateScopeRefFromUrl to include hash in its Location shape and preserve
the current fragment when constructing the replacement URL. Append location.hash
after the pathname and updated query string so removing scopeRef does not change
the active in-page section.

@BigSimmo

Copy link
Copy Markdown
Owner Author

Closing per open-PR hygiene review (2026-07-26).

Prior review found a P1: isDashboardModeHref treats only /? as dashboard-resident, so Answer to Documents (/documents/search, which keeps ClinicalDashboard mounted) skips setSearchMode/setQuery and can fire an unintended answer generation under run=1. That guard is still present on current head 7bceebf.

The branch is also heavily conflicting vs current main (globals.css, ClinicalDashboard, search shell/header, docs) and still carries a mismatched PR body.

Do not merge. Re-implement on a fresh branch from main; gate leave-dashboard with shouldRenderClinicalDashboard so Documents stays on the in-shell path.

@BigSimmo BigSimmo closed this Jul 26, 2026
BigSimmo added a commit that referenced this pull request Jul 26, 2026
Capture the 2026-07-26 close decisions and merge-ready keep list after
re-triaging the Antigravity/Cursor queue.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants